Various data processing contexts may generate data items to be further processed in a specific order and one mechanism by which this may be administered is to hold those generated data items in a queued sequence in a ring buffer, wherein newly generated data items are added to the tail end of the queued sequence, whilst data items are removed from the head end of the queued sequence for the further processing. This queued sequence of data items held in the ring buffer can provide a centralised store of generated data items which require further processing, to which multiple “producers” operating in the data processing system may add generated data items and from which multiple “consumers” in the data processing system may remove data items for further processing. However, this interaction of multiple producers and consumers with the ring buffer can mean that the action of one producer or consumer with respect to the content of the ring buffer can block other producers or consumers from carrying out their own interactions with the ring buffer. In a lock-based approach only one producer or consumer can access the ring buffer at a time and this can thus become a significant bottleneck in throughput. Moreover, even in “lock-less” ring buffer designs one producer or consumer can still block other producers or consumers from completing due to the constraint that they must release their updates to the ring buffer in order of ring buffer acquisition (i.e. in the order of the queued sequence of data items) in order to preserve the correct ordering of the ring buffer and of the updates that are made to it. If an earlier producer or consumer is stalled (for example in an interaction with another system component, e.g. a cache miss), then later producers or consumers must wait until the earlier producer or consumer completes. This creates both non-determinism (latencies and stalls in one thread may propagate to other threads) and also creates scalability problems (since the multiple threads are effectively passing a symbolic token between them in order to complete, and this creates a serialisation of all involved threads).